<?php
/**
 * Created by PhpStorm.
 * User: happy
 * Date: 19/4/20
 * Time: 下午3:56
 * http://localhost:8900/app/index.php?act=coroutine&op=demo
 */
class coroutineControl extends Control{


    public  function  index(){
       // $aa=5/0;
        $this->echos('aaabcdFG') ;
    }
    //异步io测试 4.3208599090576ms
   public  function  coroutine_demo(){

       $time1=microtime(true);
       ob_start();
       echo '<br/>all start1';
       //经测试协程间执行顺序是不确定的,协程里依然是按照顺序执行的
       for($i=0;$i<10;$i++){
        go(function() use($i){
            write('inner start'.$i);
            co::sleep(2);//休眠2秒 IO阻塞
            write('inner end'.$i);
        });
      }
       echo '<br/>all end1';
     $content= ob_get_contents();
     ob_clean();
       $diff=microtime(true)-$time1;
       $diff*=1000;
       write($diff.'ms','time.log');
      $this->end($content);
   }

   //测试非协程时间 849.48992729187ms
   public  function  no_coroutine(){
       $time1=microtime(true);
       ob_start();
       echo '<br/>all start1';
       //经测试协程执行顺序是不确定的
       for($i=0;$i<100;$i++){
           write('inner start'.$i);
           //sleep(2);
           //co::sleep(2);//休眠2秒 IO阻塞
           write('inner end'.$i);
       }
       echo '<br/>all end1';
       $content= ob_get_contents();
       ob_clean();
       $diff=microtime(true)-$time1;
       $diff*=1000;
       write($diff.'ms','time.log');
       $this->end($content);
   }

   //使用通道的例子
    public  function  channel_demo(){

       $channel=new  Swoole\Coroutine\Channel();
       go(function() use ($channel){
            $exec_result=[1,2,3,5,6];
            $channel->push($exec_result);
       });

       go(function () use($channel){
           $result=$channel->pop();
           write($result);
           var_dump($result);
       });

      $this->end('ok');
    }

    //通道例子 ,会一直循环，奇怪的,因为加载的html代码会执行
    public  function  channel_demo2(){
       $channel=new Swoole\Coroutine\Channel();
       go(function () use($channel){
           $client=new Swoole\Coroutine\Http\Client('www.baidu.com',443,true);
           $client->get('/index.php');
           $channel->push($client->body);
       });

       $str=$channel->pop();
       $this->echos(htmlspecialchars($str));
    }

    //channel设置为0，push一次就满了，挂起，pop消费后才能再push，
    public  function  channel_demo3(){
        $chan = new chan(2);
# 协程1
        go (function () use ($chan) {
            $result = [];
            //达到指定pop次数后退出
            for ($i = 0; $i < 2; $i++)
            {
                $result += $chan->pop();
            }
            var_dump($result);
        });
//两个获取网址内容的协程 是并发执行的,随机存储到channel中
# 协程2  push后pop和处理程序自定调用
        go(function () use ($chan) {
            $cli = new Swoole\Coroutine\Http\Client('www.qq.com', 80);
            $cli->set(['timeout' => 10]);
            $cli->setHeaders([
                'Host' => "www.qq.com",
                "User-Agent" => 'Chrome/49.0.2587.3',
                'Accept' => 'text/html,application/xhtml+xml,application/xml',
                'Accept-Encoding' => 'gzip',
            ]);

            $ret = $cli->get('/');
            // $cli->body 响应内容过大，这里用 Http 状态码作为测试
            $chan->push(['www.qq.com' => $cli->statusCode]);
        });

# 协程3，push后pop和处理程序会自动调用
        go(function () use ($chan) {
            $cli = new Swoole\Coroutine\Http\Client('www.163.com', 80);
            $cli->set(['timeout' => 10]);
            $cli->setHeaders([
                'Host' => "www.163.com",
                "User-Agent" => 'Chrome/49.0.2587.3',
                'Accept' => 'text/html,application/xhtml+xml,application/xml',
                'Accept-Encoding' => 'gzip',
            ]);
            $ret = $cli->get('/');
            // $cli->body 响应内容过大，这里用 Http 状态码作为测试
            $chan->push(['www.163.com' => $cli->statusCode]);
        });
    }

    //协程退出回调，清理操作等
    public  function  coroutine_demo4(){

        go(function () {
            echo "a";
            defer(function () {//协程退出执行
                echo "~a";
            });
            echo "b";
            defer(function () {//协程退出执行
                echo "~b";
            });
            sleep(1);
            echo "c";
        });
    }


    //测试数据库连接 ,测试可用
    public  function  test_swoole_mysql(){
        $db = new Swoole\Coroutine\MySQL(1);//1无意义，type不知道代表什么意思
        $db_config=c('db');
        $db_mater=$db_config['master'];
        write($db_mater);

        $db->connect([
            'host' => $db_mater['dbhost'],
            'port' => $db_mater['dbport'],
            'user' => $db_mater['dbuser'],
            'password' =>$db_mater['dbpwd'],
            'database' => $db_mater['dbname'],
        ]);

        $data = $db->query(Model3('user')->preview()->limit(2)->select());
        $this->end(json_encode($data));
    }

    public  function  test_general_mysql(){
        $data =Model3('user')->limit(2)->select();
        $this->end(json_encode($data));
    }

    //协程内部使用的组件
    public  function  coroutine_class(){
       go(function(){
           //异步函数
           Co::sleep(2);
           Co::readFile('a.log');
           Co::writeFile('b.log','bbb',0);//1为追加0为覆盖写

           $client=new Swoole\Coroutine\Http\Client('www.baidu.com',443,true);
           $client->get('/index.php');
         //  $channel->push($client->body);

           $redis = new Swoole\Coroutine\Redis();
           $redis->connect('redis', 6379);

           $db = new Swoole\Coroutine\MySQL(1);//1无意义，type不知道代表什么意思
           $db_config=c('db');
           $db_mater=$db_config['master'];
           $db->connect([
               'host' => $db_mater['dbhost'],
               'port' => $db_mater['dbport'],
               'user' => $db_mater['dbuser'],
               'password' =>$db_mater['dbpwd'],
               'database' => $db_mater['dbname'],
           ]);

           $data = $db->query(Model3('m_user')->preview()->limit(2)->select());
           $this->end(json_encode($data));

         //  $socket=new Swoole\Coroutine\Socket();

          // $mysql_client=new Swoole\Coroutine\MySQL\;

       });
    }

}